package com.xhwl.centiotdata.pushtrigger.alarm.subscribe;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.pojo.constant.DaHuaIccConstant;
import com.xhwl.centiotdata.pojo.constant.IVS1800Constant;
import com.xhwl.centiotdata.pollingtrigger.ScheduleDispatcher;
import com.xhwl.centiotdata.service.integrateconfig.AlarmIntegrationConfig;
import com.xhwl.centiotdata.utils.ThreadPoolUtils;
import com.xhwl.common.dto.cent.alarm.AlarmIntegrationConfigDTO;
import com.xhwl.common.dto.cent.alarm.dahuaicc.ICCResult;
import com.xhwl.common.dto.cent.alarm.dahuaicc.ICCSubscribeListResult;
import com.xhwl.common.dto.cent.alarm.haiwei1800.*;
import com.xhwl.common.enums.ProductEnum;
import com.xhwl.common.utils.RSAUtils;
import com.xhwl.common.utils.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.xpath.operations.Bool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class DahuaICCSubscribe implements ScheduleDispatcher {

    @Autowired
    AlarmIntegrationConfig alarmIntegrationConfig;

    private static final List<AlarmIntegrationConfigDTO> integrationConfigList = new ArrayList<>();

    @Override
    public void doOneMinutesTask() {

    }

    @Override
    public void doTenMinutesTask () {
        ThreadPoolUtils.alarmExecutor.execute(this::getToken);
    }

    @EventListener
    public void listenIntegrationConfig(AlarmIntegrationConfigEvent event) {
        ThreadPoolUtils.alarmExecutor.execute(this::getToken);
    }

    private void getToken() {
        syncConfig();
        for (AlarmIntegrationConfigDTO configDTO : integrationConfigList) {
            try {
                log.info("======= DahuaICC 开始 ===================: {}", configDTO);
                if (StringUtils.isEmpty(configDTO.getToken())) {
                    String token = login(configDTO);
                    if (!StringUtils.isEmpty(token)) {
                        configDTO.setToken(token);
                        alarmSubscribe(configDTO);
                    }
                } else {
                    configDTO.setToken(login(configDTO));
                }
            }
            catch (Exception e) {
                log.error("大华icc 订阅失败 {}", e.getMessage());
            }
        }
    }

    private void syncConfig() {
        List<AlarmIntegrationConfigDTO> list = alarmIntegrationConfig.getIntegrationProductConfig(
                null, ProductEnum.DAHUA_ICC.getId());
        for (AlarmIntegrationConfigDTO i : list) {
            if (ObjectUtils.isEmpty(i)) {
                log.error("大华icc 告警集成配置为空，{}", i);
                continue;
            }
            for (AlarmIntegrationConfigDTO j : integrationConfigList) {
                if (Objects.nonNull(j.getToken()) && Objects.equals(j.getRowId(), i.getRowId())) {
                    i.setToken(j.getToken());
                }
            }
        }
        integrationConfigList.clear();
        integrationConfigList.addAll(list);
    }

    public static void alarmSubscribe(AlarmIntegrationConfigDTO configDTO) {
        if (StringUtils.isEmpty(configDTO.getAlarmCallback())) {
            log.info("icc 告警订阅地址为空，{}", configDTO);
            configDTO.setToken(null);
            return;
        }

        try {
            String token = configDTO.getToken();
            String alarmCallback = configDTO.getAlarmCallback()
                    .replace("{rowId}", configDTO.getRowId().toString());
            String url = configDTO.getIpAndPort() + DaHuaIccConstant.SUBSCRIBE_URL;
            String subscribeMagic = getSubscribeMagic(alarmCallback);
            String subscribeName = "cent_iot_data_" + subscribeMagic;
            if (StringUtils.isEmpty(subscribeMagic)) {
                configDTO.setToken(null);
                log.error("icc 告警回调地址 ip port 提取失败: {}", configDTO);
                return;
            }

            // 删除订阅
            try {
                Map<String, List<ICCSubscribeListResult.Subscribe>> subscribeRes = getSubscribeMap(configDTO);
                for (String key : subscribeRes.keySet()) {
                    delSubscribe(configDTO, key);
                }
            } catch (Exception e) {
                configDTO.setToken(null);
                log.info("ICC 告警订阅删除失败: {}", e.getMessage());
            }

            JSONObject params = new JSONObject();
            JSONObject param = new JSONObject();
            params.put("param", param);

            JSONObject subsystem = new JSONObject();
            subsystem.put("subsystemType", 0);
            subsystem.put("name", subscribeName);
            subsystem.put("magic", subscribeMagic);
            param.put("subsystem", subsystem);

            JSONArray monitors = new JSONArray();
            JSONObject monitor = new JSONObject();
            monitor.put("monitor", alarmCallback);
            monitor.put("monitorType", "url");
            monitors.add(monitor);
            param.put("monitors", monitors);

            JSONArray events = new JSONArray();
            JSONObject event = new JSONObject();
            event.put("category", "alarm");
            event.put("subscribeAll", 1);
            event.put("domainSubscribe", 2);
            events.add(event);
            monitor.put("events", events);

            String result = HttpRequest
                    .post(url)
                    .header("Authorization", "bearer " + token)
                    .body(params.toJSONString())
                    .execute()
                    .body();
            ICCResult iccResult = JSONObject.parseObject(result, ICCResult.class);
            if (Objects.equals(iccResult.getCode(), "0")) {
                log.error("icc 告警订阅 成功: {}，{}", configDTO, iccResult);
            } else {
                log.error("icc 告警订阅 失败: {}，{}", configDTO, iccResult);
                configDTO.setToken(null);
            }
        } catch (Exception e) {
            configDTO.setToken(null);
            log.error("icc 告警订阅 失败: {}，{}", configDTO, e);
        }
    }

    public static Boolean delSubscribe(AlarmIntegrationConfigDTO configDTO, String name) {
        String url = configDTO.getIpAndPort()
                + DaHuaIccConstant.SUBSCRIBE_URL
                + "?name=" + name;
        String token = configDTO.getToken();
        String result = HttpRequest
                .delete(url)
                .header("Authorization", "bearer " + token)
                .execute()
                .body();
        ICCResult iccResult = JSONObject.parseObject(result, ICCResult.class);
        if (Objects.equals(iccResult.getCode(), "0")) {
            log.info("ICC 告警订阅删除成功: {}", name);
            return true;
        }
        log.info("ICC 告警订阅删除失败: {} , : {}", name , iccResult);
        return false;
    }

    public static Map<String, List<ICCSubscribeListResult.Subscribe>> getSubscribeMap(AlarmIntegrationConfigDTO configDTO) {
        String url = configDTO.getIpAndPort() + DaHuaIccConstant.SUBSCRIBE_LIST_URL;
        String token = configDTO.getToken();
        String alarmCallback = configDTO.getAlarmCallback()
                .replace("{rowId}", configDTO.getRowId().toString());

        Map<String, List<ICCSubscribeListResult.Subscribe>> subscribeRes = new HashMap<>();
        String result = HttpRequest
                .get(url)
                .header("Authorization", "bearer " + token)
                .form("category", "alarm")
                .form("monitorType", "url")
                .execute()
                .body();
        ICCResult iccResult = JSONObject.parseObject(result, ICCResult.class);
        if (Objects.equals(iccResult.getCode(), "0")) {
            ICCSubscribeListResult subscribeListResult = JSONObject.parseObject(iccResult.getData(), ICCSubscribeListResult.class);
            Map<String, List<ICCSubscribeListResult.Subscribe>> subscribeMap = subscribeListResult.getSubscribeMap();
            for (String key : subscribeMap.keySet()) {
                List<ICCSubscribeListResult.Subscribe> list = subscribeMap.get(key);
                for (ICCSubscribeListResult.Subscribe subscribe : list) {
                    if (Objects.equals(subscribe.getMonitor(), alarmCallback)) {
                        subscribeRes.put(key, list);
                        break;
                    }
                }
            }
        }
        return subscribeRes;
    }

    private static String login(AlarmIntegrationConfigDTO configDTO) {
        String publicKey = getPublicKey(configDTO);
        if (StringUtils.isEmpty(publicKey)) {
            log.error("大华ICC公匙获取失败");
            return null;
        }
        String url = configDTO.getIpAndPort() + DaHuaIccConstant.LOGIN_URL;
        String accessToken = "";
        JSONObject param = new JSONObject();
        param.put("grant_type", "password");
        param.put("username", configDTO.getLoginName());
        param.put("password", RSAUtils.encrypt(configDTO.getPassword(), publicKey));
        param.put("client_id", configDTO.getAk());
        param.put("client_secret", configDTO.getSk());
        param.put("public_key", publicKey);
        try {
            String body = HttpUtil.createPost(url)
                    .body(param.toJSONString())
                    .execute()
                    .body();
            String nowToken = JSON.parseObject(body).get("data").toString();
            log.info("获取大华ICC token: {}", nowToken);
            JSONObject jsonObject = JSONObject.parseObject(nowToken);
            accessToken = jsonObject.getString("access_token");
        } catch (Exception e) {
            log.error("icc request error, url: " + url, e);
        }
        return accessToken;
    }

    private static String getPublicKey(AlarmIntegrationConfigDTO configDTO) {
        String url = configDTO.getIpAndPort() + DaHuaIccConstant.PUBLIC_KEY_URL;
        String key = "";
        try {
            String body = HttpRequest.get(url).execute().body();
            JSONObject jsonObject = JSONObject.parseObject(body);
            JSONObject data = jsonObject.getJSONObject("data");
            key = data.getString("publicKey");
        } catch (Exception e) {
            log.error("大华ICC获取公钥失败: {}", e.getMessage());
        }
        return key;
    }

    private static String getSubscribeMagic(String url) throws MalformedURLException {
        URL urlRes = new URL(url);
        return urlRes.getHost() + "_" + urlRes.getPort();
    }
}
